﻿

namespace Common.Algorithm.Core.LocalTest;


/// <summary>
/// 二元方程   HimmelblauFunction
/// </summary>
public class HimmelblauFunction : ITargetFunction
{
    /// <summary>
    /// 一个自变量的二进制长度
    /// </summary>
    public int binaryLen { get; set; } = 16;

    /// <summary>
    /// 整个序列长度
    /// </summary>
    public int sequenceLen { get; set; }

    /// <summary>
    /// 定义域
    /// </summary>
    public IList<double[]> ranges { get; set; } = new List<double[]>() {
            new double[] {  -5d, 5d },
            new double[] {  -5d, 5d },
        };
    public HimmelblauFunction( )
    {
        //ranges决定自变量数量  一个自变量采用16位二进制编码  故序列总长为 n*16  
        sequenceLen = ranges.Count * binaryLen;// _sequenceLen;
    }


    /// <summary>
    ///     function : f = (x^2+y-11)^2+(x+y^2-7)^2
    ///     f(3.0,2.0)=0
    ///     f(-2.805118,3.131312))=0
    ///     f(-3.779310,-3.283186)=0
    ///     f(3.584428,-1.848126)=0
    /// </summary>
    /// <param name="ranges"></param>
    /// <returns></returns>
    public Func<double[], double> GenMathFunction()
    {
        Func<double[], double> func = (pnt) =>
        {
            var x = pnt[0];
            var y = pnt[1];
            double res = Math.Pow((x * x + y - 11), 2) + Math.Pow((x + y * y - 7), 2);
            return res;
        };
        return func;
    }

    /// <summary>
    /// 二进制转码  采用16位
    /// </summary>
    /// <param name="values"></param>
    /// <returns></returns>
    public double[] BinaryDecode(int[] values)
    {
        List<double> doubles = new List<double>(0);

        for (int i = 0; i < ranges.Count; i++)
        {
            var argument = ranges[i];
            int len = binaryLen;
            List<int> bins = values.ToList().GetRange(len * i, len);
            var bin = Convert.ToInt16(string.Join("", bins), 2);
            var num = argument.Average() + bin * (argument[1] - argument[0]) / (Math.Pow(2, len) - 1);//2^16-1=65534
            doubles.Add(num);
        }
        return doubles.ToArray();
    }
}
